<template>
  <div class="image-compressor">
    <button @click="returnFn" class="btn btn-primary retrunBUtton">
      <i class="icon">⚡</i> 返回
    </button>
    <div class="container">
      <header class="tool-header">
        <h1>图片压缩工具</h1>
        <p class="subtitle">在线压缩图片，保持质量的同时减小文件大小</p>
      </header>

      <div class="tool-content">
        <!-- 上传区域 -->
        <div class="upload-section">
          <div
            class="upload-area"
            @click="triggerFileInput"
            @drop="handleDrop"
            @dragover.prevent
            :class="{ dragover: isDragover }"
          >
            <input
              type="file"
              ref="fileInput"
              @change="handleFileSelect"
              accept="image/*"
              style="display: none"
              multiple
            />
            <div class="upload-icon">
              <span v-if="!selectedImages.length">📁</span>
              <span v-else>🖼️</span>
            </div>
            <p v-if="!selectedImages.length">点击选择图片或拖拽图片到这里</p>
            <p v-else>已选择 {{ selectedImages.length }} 张图片</p>
            <small>支持 JPG、PNG、WebP 格式，最大 10MB</small>
          </div>
        </div>

        <!-- 压缩选项 -->
        <div v-if="selectedImages.length > 0" class="options-section">
          <h3>压缩设置</h3>
          <div class="options-grid">
            <div class="option-group">
              <label>压缩质量：</label>
              <div class="slider-container">
                <input
                  type="range"
                  v-model="compressionOptions.quality"
                  min="10"
                  max="100"
                  step="5"
                  class="quality-slider"
                />
                <span class="slider-value">{{ compressionOptions.quality }}%</span>
              </div>
              <small>质量越低，文件越小</small>
            </div>

            <div class="option-group">
              <label>最大宽度：</label>
              <input
                type="number"
                v-model="compressionOptions.maxWidth"
                min="100"
                max="5000"
                class="size-input"
              />
              <small>像素，0表示不限制</small>
            </div>

            <div class="option-group">
              <label>最大高度：</label>
              <input
                type="number"
                v-model="compressionOptions.maxHeight"
                min="100"
                max="5000"
                class="size-input"
              />
              <small>像素，0表示不限制</small>
            </div>

            <div class="option-group">
              <label>输出格式：</label>
              <select v-model="compressionOptions.outputFormat">
                <option value="original">原格式</option>
                <option value="jpeg">JPEG</option>
                <option value="png">PNG</option>
                <option value="webp">WebP</option>
              </select>
            </div>

            <div class="option-group">
              <label class="checkbox-label">
                <input type="checkbox" v-model="compressionOptions.preserveExif" />
                <span class="checkmark"></span>
                保留EXIF信息
              </label>
            </div>
          </div>

          <div class="action-buttons">
            <button @click="compressAll" class="compress-btn" :disabled="isCompressing">
              {{ isCompressing ? '压缩中...' : `压缩 ${selectedImages.length} 张图片` }}
            </button>
            <button @click="clearAll" class="clear-btn">清空所有</button>
          </div>
        </div>

        <!-- 图片列表 -->
        <div v-if="selectedImages.length > 0" class="images-section">
          <h3>图片列表</h3>
          <div class="images-grid">
            <div v-for="(image, index) in selectedImages" :key="image.id" class="image-item">
              <div class="image-preview">
                <img :src="image.previewUrl" :alt="image.name" />
                <div class="image-overlay">
                  <button @click="removeImage(index)" class="remove-btn">×</button>
                </div>
              </div>

              <div class="image-info">
                <div class="image-name">{{ image.name }}</div>
                <div class="image-size">{{ formatFileSize(image.size) }}</div>

                <div v-if="image.compressed" class="compression-result">
                  <div class="size-comparison">
                    <span class="original-size">{{ formatFileSize(image.size) }}</span>
                    <span class="arrow">→</span>
                    <span class="compressed-size">{{ formatFileSize(image.compressedSize) }}</span>
                  </div>
                  <div class="compression-ratio">
                    压缩率: {{ calculateCompressionRatio(image) }}%
                  </div>
                  <button @click="downloadImage(image)" class="download-btn">下载</button>
                </div>
                <div v-else class="compression-pending">等待压缩...</div>
              </div>
            </div>
          </div>
        </div>

        <!-- 批量操作 -->
        <div v-if="compressedImages.length > 0" class="batch-section">
          <h3>批量操作</h3>
          <div class="batch-actions">
            <button @click="downloadAll" class="batch-download-btn">
              📥 下载所有压缩图片 ({{ compressedImages.length }}张)
            </button>
            <button @click="clearCompressed" class="batch-clear-btn">清空压缩结果</button>
          </div>
        </div>

        <!-- 统计信息 -->
        <div v-if="compressedImages.length > 0" class="stats-section">
          <h3>压缩统计</h3>
          <div class="stats-grid">
            <div class="stat-item">
              <span class="stat-label">总压缩图片</span>
              <span class="stat-value">{{ compressedImages.length }}</span>
            </div>
            <div class="stat-item">
              <span class="stat-label">总大小减少</span>
              <span class="stat-value">{{ calculateTotalSizeReduction() }}</span>
            </div>
            <div class="stat-item">
              <span class="stat-label">平均压缩率</span>
              <span class="stat-value">{{ calculateAverageRatio() }}%</span>
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, watch } from 'vue'
import { useRouter } from 'vue-router'
// 响应式数据
const fileInput = ref(null)
const selectedImages = ref([])
const isCompressing = ref(false)
const isDragover = ref(false)
const Router = useRouter()
const returnFn = () => {
  Router.go(-1)
}
// 压缩选项
const compressionOptions = ref({
  quality: 80,
  maxWidth: 0,
  maxHeight: 0,
  outputFormat: 'original',
  preserveExif: false
})

// 图片ID计数器
let imageIdCounter = 0

// 触发文件选择
const triggerFileInput = () => {
  fileInput.value?.click()
}

// 处理文件选择
const handleFileSelect = (event) => {
  const files = Array.from(event.target.files)
  processImageFiles(files)
}

// 处理拖拽
const handleDrop = (event) => {
  event.preventDefault()
  isDragover.value = false
  const files = Array.from(event.dataTransfer.files).filter(file =>
    file.type.startsWith('image/')
  )
  processImageFiles(files)
}

// 处理图片文件
const processImageFiles = async (files) => {
  for (const file of files) {
    if (file.size > 10 * 1024 * 1024) {
      alert(`文件 ${file.name} 超过10MB限制，已跳过`)
      continue
    }

    try {
      const previewUrl = await createPreviewUrl(file)
      selectedImages.value.push({
        id: imageIdCounter++,
        file: file,
        name: file.name,
        size: file.size,
        previewUrl: previewUrl,
        compressed: false,
        compressedBlob: null,
        compressedSize: 0
      })
    } catch (error) {
      console.error('处理图片失败:', error)
    }
  }
}

// 创建预览URL
const createPreviewUrl = (file) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader()
    reader.onload = (e) => resolve(e.target.result)
    reader.onerror = reject
    reader.readAsDataURL(file)
  })
}

// 压缩单张图片
const compressImage = (image) => {
  return new Promise((resolve) => {
    const img = new Image()
    img.onload = () => {
      const canvas = document.createElement('canvas')
      const ctx = canvas.getContext('2d')

      // 计算新尺寸
      let width = img.width
      let height = img.height

      if (compressionOptions.value.maxWidth > 0 && width > compressionOptions.value.maxWidth) {
        height = (height * compressionOptions.value.maxWidth) / width
        width = compressionOptions.value.maxWidth
      }

      if (compressionOptions.value.maxHeight > 0 && height > compressionOptions.value.maxHeight) {
        width = (width * compressionOptions.value.maxHeight) / height
        height = compressionOptions.value.maxHeight
      }

      canvas.width = width
      canvas.height = height

      // 绘制图片
      ctx.drawImage(img, 0, 0, width, height)

      // 获取输出格式
      let format = 'image/jpeg'
      if (compressionOptions.value.outputFormat === 'png') {
        format = 'image/png'
      } else if (compressionOptions.value.outputFormat === 'webp') {
        format = 'image/webp'
      } else {
        format = image.file.type
      }

      // 质量设置（PNG格式忽略质量参数）
      const quality = format === 'image/png' ? 1 : compressionOptions.value.quality / 100

      // 转换为Blob
      canvas.toBlob((blob) => {
        resolve(blob)
      }, format, quality)
    }
    img.src = image.previewUrl
  })
}

// 压缩所有图片
const compressAll = async () => {
  isCompressing.value = true

  for (let i = 0; i < selectedImages.value.length; i++) {
    const image = selectedImages.value[i]
    try {
      const compressedBlob = await compressImage(image)
      const compressedUrl = URL.createObjectURL(compressedBlob)

      // 更新图片信息
      selectedImages.value[i] = {
        ...image,
        compressed: true,
        compressedBlob: compressedBlob,
        compressedSize: compressedBlob.size,
        compressedUrl: compressedUrl
      }
    } catch (error) {
      console.error(`压缩图片 ${image.name} 失败:`, error)
    }
  }

  isCompressing.value = false
}

// 下载单张图片
const downloadImage = (image) => {
  if (!image.compressedBlob) return

  const link = document.createElement('a')
  const extension = getFileExtension(image)
  link.download = `compressed_${image.name.replace(/\.[^/.]+$/, '')}.${extension}`
  link.href = image.compressedUrl
  link.click()
}

// 下载所有压缩图片
const downloadAll = async () => {
  for (const image of compressedImages.value) {
    await new Promise(resolve => setTimeout(resolve, 100)) // 避免同时下载太多文件
    downloadImage(image)
  }
}

// 获取文件扩展名
const getFileExtension = (image) => {
  if (compressionOptions.value.outputFormat !== 'original') {
    return compressionOptions.value.outputFormat
  }
  return image.name.split('.').pop() || 'jpg'
}

// 移除图片
const removeImage = (index) => {
  if (selectedImages.value[index].compressedUrl) {
    URL.revokeObjectURL(selectedImages.value[index].compressedUrl)
  }
  selectedImages.value.splice(index, 1)
}

// 清空所有
const clearAll = () => {
  selectedImages.value.forEach(image => {
    if (image.compressedUrl) {
      URL.revokeObjectURL(image.compressedUrl)
    }
  })
  selectedImages.value = []
}

// 清空压缩结果
const clearCompressed = () => {
  selectedImages.value.forEach(image => {
    if (image.compressedUrl) {
      URL.revokeObjectURL(image.compressedUrl)
    }
    image.compressed = false
    image.compressedBlob = null
    image.compressedSize = 0
    image.compressedUrl = null
  })
}

// 计算压缩率
const calculateCompressionRatio = (image) => {
  if (!image.compressed) return 0
  const reduction = ((image.size - image.compressedSize) / image.size) * 100
  return Math.round(reduction)
}

// 计算总大小减少
const calculateTotalSizeReduction = () => {
  const totalOriginal = selectedImages.value.reduce((sum, img) => sum + img.size, 0)
  const totalCompressed = compressedImages.value.reduce((sum, img) => sum + img.compressedSize, 0)
  const reduction = totalOriginal - totalCompressed
  return formatFileSize(reduction)
}

// 计算平均压缩率
const calculateAverageRatio = () => {
  if (compressedImages.value.length === 0) return 0
  const totalRatio = compressedImages.value.reduce((sum, img) =>
    sum + calculateCompressionRatio(img), 0
  )
  return Math.round(totalRatio / compressedImages.value.length)
}

// 格式化文件大小
const formatFileSize = (bytes) => {
  if (bytes === 0) return '0 B'
  const k = 1024
  const sizes = ['B', 'KB', 'MB', 'GB']
  const i = Math.floor(Math.log(bytes) / Math.log(k))
  return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

// 计算属性
const compressedImages = computed(() =>
  selectedImages.value.filter(img => img.compressed)
)

// 监听拖拽状态
watch(isDragover, (newVal) => {
  if (newVal) {
    setTimeout(() => {
      isDragover.value = false
    }, 100)
  }
})
</script>

<style scoped>
.btn {
  padding: 8px 15px;
  border: none;
  border-radius: 6px;
  cursor: pointer;
  font-size: 20px;
  font-weight: 500;
  display: flex;
  align-items: center;
  gap: 5px;
  transition: all 0.3s ease;
}

.btn-primary {
  background: linear-gradient(to right, #667eea, #764ba2);
  color: white;
}
.retrunBUtton {
  position: absolute;
  top: 100px;
  right: 100px;
}
.image-compressor {
  min-height: 100vh;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  padding: 20px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
  position: relative;
}

.container {
  max-width: 1200px;
  margin: 0 auto;
  background: white;
  border-radius: 12px;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
}

.tool-header {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: white;
  padding: 30px;
  text-align: center;
  border-radius: 12px 12px 0 0;
}

.tool-header h1 {
  margin: 0 0 10px 0;
  font-size: 2.2em;
}

.subtitle {
  margin: 0;
  opacity: 0.9;
  font-size: 1.1em;
}

.tool-content {
  padding: 30px;
}

.upload-section {
  margin-bottom: 30px;
}

.upload-area {
  border: 2px dashed #667eea;
  border-radius: 8px;
  padding: 40px 20px;
  text-align: center;
  cursor: pointer;
  transition: all 0.3s;
  background: #f8f9ff;
}

.upload-area:hover,
.upload-area.dragover {
  border-color: #764ba2;
  background: #f0f2ff;
  transform: translateY(-2px);
}

.upload-icon {
  font-size: 3em;
  margin-bottom: 15px;
}

.options-section {
  background: #f8f9fa;
  padding: 25px;
  border-radius: 8px;
  margin-bottom: 30px;
}

.options-section h3 {
  margin-bottom: 20px;
  color: #333;
}

.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
}

.option-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.option-group label {
  font-weight: 600;
  color: #555;
}

.slider-container {
  display: flex;
  align-items: center;
  gap: 15px;
}

.quality-slider {
  flex: 1;
  height: 6px;
  border-radius: 3px;
  background: #ddd;
  outline: none;
}

.quality-slider::-webkit-slider-thumb {
  appearance: none;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: #667eea;
  cursor: pointer;
}

.slider-value {
  font-weight: 600;
  color: #667eea;
  min-width: 50px;
}

.size-input {
  padding: 8px 12px;
  border: 2px solid #ddd;
  border-radius: 6px;
  font-size: 18px;
  max-width: 120px;
}

select {
  padding: 8px 12px;
  border: 2px solid #ddd;
  border-radius: 6px;
  font-size: 18px;
  max-width: 200px;
}

.checkbox-label {
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  font-size: 24px;
}

.checkbox-label input {
  display: none;
}

.checkmark {
  width: 18px;
  height: 18px;
  border: 2px solid #ddd;
  border-radius: 3px;
  position: relative;
  transition: all 0.3s;
}

.checkbox-label input:checked + .checkmark {
  background: #667eea;
  border-color: #667eea;
}

.checkbox-label input:checked + .checkmark::after {
  content: '✓';
  position: absolute;
  color: white;
  font-size: 20px;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}

.action-buttons {
  display: flex;
  gap: 15px;
}

.compress-btn,
.clear-btn,
.batch-download-btn,
.batch-clear-btn {
  padding: 12px 24px;
  border: none;
  border-radius: 6px;
  font-size: 18px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s;
}

.compress-btn {
  background: #4caf50;
  color: white;
}

.compress-btn:hover:not(:disabled) {
  background: #45a049;
  transform: translateY(-2px);
}

.compress-btn:disabled {
  background: #cccccc;
  cursor: not-allowed;
}

.clear-btn {
  background: #ff9800;
  color: white;
}

.clear-btn:hover {
  background: #f57c00;
}

.batch-download-btn {
  background: #2196f3;
  color: white;
}

.batch-clear-btn {
  background: #f44336;
  color: white;
}

.images-section {
  margin-bottom: 30px;
}

.images-section h3 {
  margin-bottom: 20px;
  color: #333;
}

.images-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 20px;
}

.image-item {
  border: 1px solid #e0e0e0;
  border-radius: 8px;
  overflow: hidden;
  background: white;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.image-preview {
  position: relative;
  height: 200px;
  overflow: hidden;
}

.image-preview img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-overlay {
  position: absolute;
  top: 0;
  right: 0;
  padding: 5px;
}

.remove-btn {
  background: rgba(255, 0, 0, 0.8);
  color: white;
  border: none;
  border-radius: 50%;
  width: 30px;
  height: 30px;
  font-size: 18px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
}

.image-info {
  padding: 15px;
}

.image-name {
  font-weight: 600;
  margin-bottom: 5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.image-size {
  color: #666;
  font-size: 20px;
  margin-bottom: 10px;
}

.compression-result,
.compression-pending {
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
  margin-top: 10px;
}

.size-comparison {
  display: flex;
  align-items: center;
  gap: 5px;
  margin-bottom: 5px;
}

.original-size {
  color: #666;
  text-decoration: line-through;
  font-size: 20px;
}

.arrow {
  color: #667eea;
}

.compressed-size {
  color: #4caf50;
  font-weight: 600;
  font-size: 20px;
}

.compression-ratio {
  color: #ff9800;
  font-size: 20px;
  margin-bottom: 8px;
}

.download-btn {
  background: #2196f3;
  color: white;
  border: none;
  padding: 6px 12px;
  border-radius: 4px;
  font-size: 20px;
  cursor: pointer;
}

.batch-section,
.stats-section {
  background: #f8f9fa;
  padding: 20px;
  border-radius: 8px;
  margin-bottom: 20px;
}

.batch-section h3,
.stats-section h3 {
  margin-bottom: 15px;
  color: #333;
}

.batch-actions {
  display: flex;
  gap: 15px;
  flex-wrap: wrap;
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 15px;
}

.stat-item {
  background: white;
  padding: 15px;
  border-radius: 6px;
  text-align: center;
  border-left: 4px solid #667eea;
}

.stat-label {
  display: block;
  font-size: 20px;
  color: #666;
  margin-bottom: 5px;
}

.stat-value {
  display: block;
  font-size: 1.5em;
  font-weight: 600;
  color: #333;
}

@media (max-width: 768px) {
  .tool-content {
    padding: 20px;
  }

  .options-grid {
    grid-template-columns: 1fr;
  }

  .action-buttons,
  .batch-actions {
    flex-direction: column;
  }

  .images-grid {
    grid-template-columns: 1fr;
  }
}
small {
  font-size: 22px;
}
</style>